#include "gl_util.h"

MatrixStackFrame::MatrixStackFrame(GLenum matrix) : matrix(matrix) {
	glMatrixMode(matrix);
	glPushMatrix();
}

MatrixStackFrame::~MatrixStackFrame() {
	glMatrixMode(matrix);
	glPopMatrix();
}

void check() {	
	GLenum err=glGetError();

	if(err)
		die(err);
}

float centerFitRectagle(unsigned int w, unsigned int h, float minX, float maxX, float minY, float maxY) {
	float width=maxX - minX, height=maxY - minY;

	glViewport(0,0,w,h);
	
	float pAspect=(float)w/(float)h;
	float lAspect=width/height;

	if(pAspect < lAspect) {
		height *= lAspect/pAspect;
	} else {
		width *= pAspect/lAspect;
	}

	float pitch=width / (float)w;

	height /= 2; width /= 2;

	float midX=(minX + maxX)/2, midY=(minY + maxY)/2;

	glMatrixMode(GL_PROJECTION); check();
	glLoadIdentity();

	gluOrtho2D(midX - width , midX + width, midY - height, midY + height);

	return pitch;
}

vec3 project(float x, float y, float z) {
	vec3 p;
	p[0]=x; p[1]=y; p[2]=z;
	return project(p);
}

vec3 project(vec3 p) {
	double M[16], P[16];
	GLint V[4];

	glGetDoublev(GL_MODELVIEW_MATRIX, M);
	glGetDoublev(GL_PROJECTION_MATRIX, P);
	glGetIntegerv(GL_VIEWPORT, V);

	double x, y, z;
	gluProject(p[0], p[1], p[2], M, P, V, &x, &y, &z);

	p[0]=(float)x; p[1]=(float)y; p[2]=(float)z;
	return p;
}

vec3 unproject(float x, float y, float z) {
	vec3 p;
	p[0]=x; p[1]=y; p[2]=z;
	return unproject(p);
}

vec3 unproject(vec3 p) {
	double M[16], P[16];
	GLint V[4];

	glGetDoublev(GL_MODELVIEW_MATRIX, M);
	glGetDoublev(GL_PROJECTION_MATRIX, P);
	glGetIntegerv(GL_VIEWPORT, V);

	double x, y, z;
	gluUnProject(p[0], p[1], p[2], M, P, V, &x, &y, &z);

	p[0]=(float)x; p[1]=(float)y; p[2]=(float)z;
	return p;
}